home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
007
/
checklpt.arc
/
COPYLPT.C
< prev
next >
Wrap
Text File
|
1987-04-30
|
15KB
|
313 lines
/***************************************************************************/
/* */
/* Program copylpt */
/* */
/* Usage: copylpt filename [PRINTER] */
/* where filename is file to be copied (upper, lower or mixed case) */
/* and optional argument PRINTER is the printer to copy to */
/* (upper, lower or mixed case) */
/* PRN, 1 or LPT1 for LPT1, */
/* 2 or LPT2 for LPT2 or */
/* 3 or LPT3 for LPT3. */
/* If PRINTER is not specified, copy to LPT1 */
/* Returns ERRORLEVEL 0 if file filename was copied to the printer */
/* 1 if PRINTER is not available */
/* 2 if PRINTER is available, but file filename is */
/* not available. */
/* 3 if both PRINTER and file filename are */
/* available, but there was some error copying */
/* filename to PRINTER. */
/* 100 for certain system errors. */
/* */
/* I designed copylpt to copy a file to a printer if the printer */
/* is available and then inform a batch file of its success or failure. */
/* I wanted my AUTOEXEC.BAT file to copy an user-defined character set to */
/* my Epson printer if possible without stopping for a critical error if */
/* the printer is off. */
/* If the filename's path does not start with a back slash and it does, */
/* not specify a drive, copylpt looks first at the filename itself, then */
/* appends it to any paths specified in a PATH-like environment variable */
/* which has the same name as the filename's extension, then appends it to */
/* any paths in the PATH enviroment variable. Under DOS 3 or later, it */
/* finally appends it to the calling program's drive and path. */
/* copylpt requires DOS 2.0 or later to run. */
/* The ERRORLEVEL of 100 occurs only in the event of a compiler or */
/* system failure. */
/* */
/* I compiled copylpt and its subfunctions for use with Lattice C, */
/* Version 3. Some of their features which may not be portable are: */
/* _DOS is a Lattice C system variable which contains the DOS major */
/* version. */
/* fileno() is an UNIX function which returns the file handle for a */
/* file pointer. */
/* Lattice classes onerror(action) as a MSDOS function. onerror(1) */
/* preeempts the MSDOS critical error handler. onerror(0) restores the */
/* MSDOS critical error handler. */
/* getfc(fh, cw) returns 0 if fh is a valid file handle, -1 otherwise. */
/* If it is a valid file handle, the function sets cw to the */
/* word for the file. Bit 7 is 0 for a disk file. See DOS interrupt 44H, */
/* AL = 0, for more information about the characteristic word */
/* union REGS is a Lattice union which lets the registers become */
/* arguments to functions which invoke 8086 interrupts. Two functions */
/* use it. Both return an int containing the flags after the interrupt. */
/* intdos invokes interrupt 21H with input registers as the first */
/* argument and returns the value of the registers after the interrupt as */
/* the second argument. int86 invokes the interrupt specified by the */
/* first argument with input registers as the second argument. It returns */
/* the value of the registers after the interrupt as the third argument. */
/* fopene is a Lattice 3 variant version of fopen which automatically */
/* searches the environment as described above. */
/* stcgfn and stcgfp are Lattice expressions which get a file name */
/* node (name and extension) and path respectively to string variables. */
/* The path does not have a trailing "\" */
/* Lattice function getdsk returns 0 if the default drive is A:, */
/* 1 if it is B:, etc. */
/* Lattice function getcd takes a drive number as its first argument, */
/* with 0 for the default drive, 1 for A:, etc. It returns the current */
/* directory in the variable pointed at by its second argument. The */
/* current directory does not include either the drive letter or the */
/* trailing back-slash. In particular, it returns an empty string for */
/* the root directory. */
/* dfind is a Lattice implementation of the DOS function which returns */
/* the directory entry which matches the input file name. Sets the DOS */
/* information in a structure which has a type FILEINFO, and it returns */
/* 0 if it can make a match, -1 otherwise. */
/* getenv(name) is a Lattice C function which returns a pointer to the */
/* information following the = sign in the DOS environment string of the */
/* form NAME=information. */
/* strupr converts a string to upper case. */
/* Lattice C sets a variable errno to a non-zero value if a standard */
/* library function detects an error. It never automatically resets */
/* errno. Errno is in error.h. */
/* */
/* Full identifiers in this program conform to the proposed ANSI */
/* standard of at most 31 significant characters, and they are different */
/* within the first 8 characters. Lattice C includes a -n compiler */
/* switch which changes the number of significant characters in */
/* identifiers from 8 to 39. While this program works without it, I */
/* designed them to use it. */
/* */
/* This file requires the functions in files CHECKLPT.C and FOPEN1.C */
/* to compile and run */
/* */
/* Lew Paper */
/* 4/18/87 */
/***************************************************************************/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <dos.h>
#include <error.h>
#include <stdlib.h>
extern char _DOS; /* Lattice system variable. DOS major */
/* version number */
static int printer_number = 1;
static char printer_name[] = "LPT1";
static FILE *printer_fp;
static int handle;
static char file_name[65];
static FILE *file_fp;
extern int errno; /* fgetc sets this to non-zero */
static char error_message_end[90]; /* Pointer to end of error message */
/* Prototypes for external functions */
int handle_check_lpt_available(int);
FILE *fopene_program(char *, char *, char *);
#define CHECK_NAME(LEGAL) !strcmpi(argv[2], "LEGAL")
#define CALLING_NAME argv[0]
#define CARRY_FLAG 1
static void close_device()
{
if (fclose(printer_fp))
fprintf(stderr, "\nError in closing printer %s\n\n", printer_name);
}
static void close_file()
{
if (fclose(file_fp))
fprintf(stderr, "\nError in closing file %s\n\n", file_name);
}
/* Write an error message to stderr, close LPT2 or LPT3 and exit with */
/* ERRORLEVEL = 1 */
static void no_copy_end()
{
fprintf(stderr, "Unable to copy file %s\nto printer %s because",
file_name, printer_name);
fputs(error_message_end, stderr);
fputs("\n\n", stderr);
if (printer_number > 1)
close_device();
}
static void write_printer_error()
{
close_file(); /* Close input file */
sprintf(error_message_end, " Error writing to printer %s",
printer_name);
no_copy_end();
exit(3);
}
static void usage()
{
fputs("Usage: copylpt filename [PRINTER]\n", stderr);
fputs(" where filename is file to be copied ",stderr);
fputs("(upper, lower or mixed case)\n", stderr);
fputs(" and optional argument PRINTER is the printer to copy to\n",
stderr);
fputs(" (upper, lower or mixed case)\n", stderr);
fputs(" PRN, 1 or LPT1 for LPT1,\n", stderr);
fputs(" 2 or LPT2 for LPT2 or\n", stderr);
fputs(" 3 or LPT3 for LPT3.\n", stderr);
fputs(" If PRINTER is not specified, copy to LPT1\n", stderr);
fputs("Returns ERRORLEVEL 0 if file filename was copied to the printer\n",
stderr);
fputs(" 1 if file filename was not copied ", stderr);
fputs("to the printer\n", stderr);
fputs(" 100 for certain system errors.\n\n", stderr);
exit(1);
} /* usage */
static void get_device_handle()
{
int cw; /* Characteristic word for file */
/* PC DOS 3.1 opens printers which are off or not installed with */
/* no error indication, so I can not test a critical error here. I */
/* preempted the critical error handler because I am not sure that */
/* some version of DOS might not treat opening a printer which */
/* doesn't exist as a critical error. */
if (onerror(1)) /* Preempt MSDOS critical error */
/* handler. */
{
fputs("onerror(1) failed in get_device_handle\n\n", stderr);
exit(100);
}
if (printer_number == 1)
printer_fp = freopen("LPT1", "wb", stdprt);
else
printer_fp = fopen(printer_name, "wb");
if (!printer_fp)
{
fprintf(stderr, "Unable to open device %s\n\n", printer_name);
exit(1);
}
if (getfc((handle = fileno(printer_fp)), &cw) || !(cw & 0x0080))
/* Invalid handle */
{
fprintf(stderr, "There is no device driver %s installed\n\n",
printer_name);
close_device();
exit(1);
}
/* The Lattice C Manual doesn't say exactly how onerror() works. */
/* I turned it off here to protect its being turned back on in */
/* FILE_check_lpt_available */
if (onerror(0)) /* Restore MSDOS critical error */
{
fputs("onerror(0) failed in get_device_handle\n\n", stderr);
close_device();
exit(100);
}
} /* get_device_handle */
main(argc, argv)
int argc;
char *argv[];
{
int c;
/* Check for DOS 2.0 or later */
if (!_DOS)
{
fputs("COPYLPT requires DOS 2.0 or later.\n\n", stderr);
exit(1);
}
switch (argc)
{
case 1: /* No file name specified */
usage(); /* Display usage and exit with */
/* ERRORLEVEL = 1. */
break;
case 2: /* Default printer */
break;
default: /* argc >= 3. Set up printer name */
/* and handle. */
if (CHECK_NAME(prn) || CHECK_NAME(1) || CHECK_NAME(lpt1))
/* Defensive programming. LPT1 is */
/* the original default printer, so */
/* these assignments are not */
/* necessary. */
printer_number = 1;
else if (CHECK_NAME(2) || CHECK_NAME(lpt2))
printer_number = 2;
else if (CHECK_NAME(3) || CHECK_NAME(lpt3))
printer_number = 3;
else
usage(); /* Display usage and exit with */
/* ERRORLEVEL = 1. */
sprintf(printer_name, "LPT%d", printer_number);
break;
}
get_device_handle();
/* Transfer upper case of file name from argv[1] to file_name. */
(void) strcpy(file_name, argv[1]);
(void) strupr(file_name);
/* Check if printer is available */
if (handle_check_lpt_available(handle))
{
sprintf(error_message_end, " printer %s was not available",
printer_name);
no_copy_end();
exit(1);
}
file_fp = fopene_program(file_name, "rb", CALLING_NAME);
if (!file_fp)
{
sprintf(error_message_end, " file %s could not be opened",
file_name);
no_copy_end();
exit(2);
}
errno = 0; /* Clear any prior errors */
while ((c = getc(file_fp)) != EOF)
if (putc(c, printer_fp) == EOF)
write_printer_error();
if (errno) /* Check for input error */
write_printer_error();
close_file();
close_device();
fprintf(stderr, "copylpt wrote file %s to printer %s\n\n",
file_name, printer_name);
} /* main */